#include <EB0/EB0.h>

namespace EB0
{
namespace Managers
{
	// Static Member
	ImageManager* ImageManager::mSingleton = 0;

#pragma region Constructor / Destructor
	// Constructor
	ImageManager::ImageManager()
	{
		// Nothing to do...
	}

	// Destructor
	ImageManager::~ImageManager()
	{
		// Destroy all images
		destroyAllImages();

		// Reset values
		mSingleton = 0;
	}
#pragma endregion

#pragma region Singleton
	// Singleton Reference
	ImageManager& ImageManager::getSingleton()
	{
		return *getSingletonPtr();
	}

	// Singleton Pointer
	ImageManager* ImageManager::getSingletonPtr()
	{
		if (!mSingleton) mSingleton = new ImageManager();
		return mSingleton;
	}
#pragma endregion

#pragma region Image Management
	// Load an image file, or return the pointer if it has already been loaded
	sf::Image* ImageManager::createImage(char* filename)
	{
		// Lock mutex; automatically unlocks when the function terminates
		sf::Lock lock(mMutex);

		// Check if an image file already exists with the given filename
		ImageMap::iterator imageIter;
		imageIter = mImages.find(filename);

		if (imageIter != mImages.end())
			return imageIter->second; // return a previously existing pointer

		// Create new image
		mImages[filename] = new sf::Image;
		mImages[filename]->LoadFromFile(filename);
		return mImages[filename];
	}

	// Unload an image file with a given pointer
	bool ImageManager::destroyImage(sf::Image*& image)
	{
		// Lock mutex; automatically unlocks when the function terminates
		sf::Lock lock(mMutex);

		// Scan through each image to determine if one exists with the given pointer
		ImageMap::iterator imageIter = mImages.begin();
		bool found = false;

		while (imageIter != mImages.end() && !found)
		{
			found = (imageIter->second == image);
			if (!found) imageIter++;
		}

		// Did the image exist? Let's delete it.
		if (found)
		{
			delete imageIter->second;
			imageIter->second = 0;
			mImages.erase(imageIter);

			// Null the given pointer as well
			image = 0;
		}

		return found;
	}

	// Unload a music file with a given filename
	bool ImageManager::destroyImage(char* filename)
	{
		// Lock mutex; automatically unlocks when the function terminates
		sf::Lock lock(mMutex);

		// Check if an image exists with the given refname
		ImageMap::iterator imageIter;
		imageIter = mImages.find(filename);

		if (imageIter != mImages.end())
		{
			delete imageIter->second;
			imageIter->second = 0;
			mImages.erase(imageIter);
			return true;
		}

		return false;
	}

	// Unload all image
	void ImageManager::destroyAllImages()
	{
		// Lock mutex; automatically unlocks when the function terminates
		sf::Lock lock(mMutex);

		// Destroy all images
		if (!mImages.empty())
		{
			ImageMap::iterator imageIter;

			for (imageIter = mImages.begin(); imageIter != mImages.end(); imageIter++)
			{
				delete imageIter->second;
				imageIter->second = 0;
			}

			mImages.clear();
		}
	}
#pragma endregion
} // namespace Managers
}